package plugin.validator;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CCombo;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.ShellAdapter;
import org.eclipse.swt.events.ShellEvent;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.pentaho.di.core.Const;
import org.pentaho.di.core.exception.KettleException;
import org.pentaho.di.core.row.RowMetaInterface;
import org.pentaho.di.i18n.BaseMessages;
import org.pentaho.di.trans.TransMeta;
import org.pentaho.di.trans.step.BaseStepMeta;
import org.pentaho.di.trans.step.StepDialogInterface;
import org.pentaho.di.ui.core.dialog.ErrorDialog;
import org.pentaho.di.ui.core.widget.TextVar;
import org.pentaho.di.ui.trans.step.BaseStepDialog;

public class PeselValidatorStepDialog extends BaseStepDialog implements
		StepDialogInterface {
	private static Class<?> PKG = PeselValidatorStepMeta.class; // for i18n
																// purposes,
																// needed by
																// Translator2!!
																// $NON-NLS-1$

	private boolean gotPreviousFields = false;

	private Label wlFieldToValidateName;
	private CCombo wFieldToValidateName;
	private FormData fdlFieldToValidateName, fdFieldToValidateName;

	private Label wlLogicalFieldName;
	private TextVar wLogicalFieldName;
	private FormData fdlLogicalFieldName, fdLogicalFieldName;

	private Label wlBirthDateFieldName;
	private TextVar wBirthDateFieldName;
	private FormData fdlBirthDateFieldName,	fdBirthDateFieldName;
	
	private Label wlSexFieldName;
	private TextVar wSexFieldName;
	private FormData fdlSexFieldName, fdSexFieldName;

	private FormData fdAdditionalFields;
	private Group wOutputFields;

	private PeselValidatorStepMeta input;

	public PeselValidatorStepDialog(Shell parent, Object in,
			TransMeta transMeta, String sname) {
		super(parent, (BaseStepMeta) in, transMeta, sname);
		input = (PeselValidatorStepMeta) in;
	}

	public String open() {
		Shell parent = getParent();
		Display display = parent.getDisplay();

		shell = new Shell(parent, SWT.DIALOG_TRIM | SWT.RESIZE | SWT.MAX
				| SWT.MIN);
		props.setLook(shell);
		setShellImage(shell, input);

		ModifyListener lsMod = new ModifyListener() {
			public void modifyText(ModifyEvent e) {
				input.setChanged();
			}
		};

		changed = input.hasChanged();

		FormLayout formLayout = new FormLayout();
		formLayout.marginWidth = Const.FORM_MARGIN;
		formLayout.marginHeight = Const.FORM_MARGIN;

		shell.setLayout(formLayout);
		shell.setText(BaseMessages.getString(PKG,
				"PeselValidatorStepDialog.Shell.Title")); //$NON-NLS-1$

		int middle = props.getMiddlePct();
		int margin = Const.MARGIN;

		// Stepname line
		wlStepname = new Label(shell, SWT.RIGHT);
		wlStepname.setText(BaseMessages.getString(PKG,
				"PeselValidatorStepDialog.Stepname.Label")); //$NON-NLS-1$
		props.setLook(wlStepname);
		fdlStepname = new FormData();
		fdlStepname.left = new FormAttachment(0, 0);
		fdlStepname.right = new FormAttachment(middle, -margin);
		fdlStepname.top = new FormAttachment(0, margin);
		wlStepname.setLayoutData(fdlStepname);
		wStepname = new Text(shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
		wStepname.setText(stepname);
		props.setLook(wStepname);
		wStepname.addModifyListener(lsMod);
		fdStepname = new FormData();
		fdStepname.left = new FormAttachment(middle, 0);
		fdStepname.top = new FormAttachment(0, margin);
		fdStepname.right = new FormAttachment(100, 0);
		wStepname.setLayoutData(fdStepname);

		// field to validate field
		wlFieldToValidateName = new Label(shell, SWT.RIGHT);
		wlFieldToValidateName.setText(BaseMessages.getString(PKG,
				"PeselValidatorStepDialog.FieldToValidateName.Label")); //$NON-NLS-1$
		props.setLook(wlFieldToValidateName);
		fdlFieldToValidateName = new FormData();
		fdlFieldToValidateName.left = new FormAttachment(0, 0);
		fdlFieldToValidateName.right = new FormAttachment(middle, -margin);
		fdlFieldToValidateName.top = new FormAttachment(wStepname, margin);
		wlFieldToValidateName.setLayoutData(fdlFieldToValidateName);

		wFieldToValidateName = new CCombo(shell, SWT.BORDER | SWT.READ_ONLY);
		props.setLook(wFieldToValidateName);
		wFieldToValidateName.addModifyListener(lsMod);
		fdFieldToValidateName = new FormData();
		fdFieldToValidateName.left = new FormAttachment(middle, 0);
		fdFieldToValidateName.top = new FormAttachment(wStepname, margin);
		fdFieldToValidateName.right = new FormAttachment(100, -margin);
		wFieldToValidateName.setLayoutData(fdFieldToValidateName);
		wFieldToValidateName.addFocusListener(new FocusListener() {
			public void focusLost(org.eclipse.swt.events.FocusEvent e) {
			}

			public void focusGained(org.eclipse.swt.events.FocusEvent e) {
				Cursor busy = new Cursor(shell.getDisplay(), SWT.CURSOR_WAIT);
				shell.setCursor(busy);
				get();
				shell.setCursor(null);
				busy.dispose();
			}
		});


		//////////////////////////////////
		// START OF Output Fields GROUP //
		//////////////////////////////////

		wOutputFields = new Group(shell, SWT.SHADOW_NONE);
		props.setLook(wOutputFields);
		wOutputFields.setText(BaseMessages.getString(PKG,
				"PeselValidatorStepDialog.OutputFields.Label"));

		FormLayout OutputFieldsgroupLayout = new FormLayout();
		OutputFieldsgroupLayout.marginWidth = 10;
		OutputFieldsgroupLayout.marginHeight = 10;
		wOutputFields.setLayout(OutputFieldsgroupLayout);

		// logical fieldname ...
		wlLogicalFieldName = new Label(wOutputFields, SWT.RIGHT);
		wlLogicalFieldName.setText(BaseMessages.getString(PKG,
				"PeselValidatorStepDialog.LogicalField.Label")); //$NON-NLS-1$
		props.setLook(wlLogicalFieldName);
		fdlLogicalFieldName = new FormData();
		fdlLogicalFieldName.left = new FormAttachment(0, -margin);
		fdlLogicalFieldName.right = new FormAttachment(middle, -2 * margin);
		fdlLogicalFieldName.top = new FormAttachment(wFieldToValidateName, 2 * margin);
		wlLogicalFieldName.setLayoutData(fdlLogicalFieldName);

		wLogicalFieldName = new TextVar(transMeta, wOutputFields, SWT.SINGLE | SWT.LEFT
				| SWT.BORDER);
		wLogicalFieldName.setToolTipText(BaseMessages.getString(PKG,
				"CreditCardValidatorDialog.ResultField.Tooltip"));
		props.setLook(wLogicalFieldName);
		wLogicalFieldName.addModifyListener(lsMod);
		fdLogicalFieldName = new FormData();
		fdLogicalFieldName.left = new FormAttachment(middle, -margin);
		fdLogicalFieldName.top = new FormAttachment(wFieldToValidateName, 2 * margin);
		fdLogicalFieldName.right = new FormAttachment(100, 0);
		wLogicalFieldName.setLayoutData(fdLogicalFieldName);

		// birthDate fieldname ...
		wlBirthDateFieldName = new Label(wOutputFields, SWT.RIGHT);
		wlBirthDateFieldName.setText(BaseMessages.getString(PKG,
				"PeselValidatorStepDialog.BirthDateField.Label")); //$NON-NLS-1$
		props.setLook(wlBirthDateFieldName);
		fdlBirthDateFieldName = new FormData();
		fdlBirthDateFieldName.left = new FormAttachment(0, -margin);
		fdlBirthDateFieldName.right = new FormAttachment(middle, -2 * margin);
		fdlBirthDateFieldName.top = new FormAttachment(wLogicalFieldName, margin);
		wlBirthDateFieldName.setLayoutData(fdlBirthDateFieldName);

		wBirthDateFieldName = new TextVar(transMeta, wOutputFields, SWT.SINGLE | SWT.LEFT
				| SWT.BORDER);
		wBirthDateFieldName.setToolTipText(BaseMessages.getString(PKG,
				"PeselValidatorStepDialog.BirthDateField.Tooltip"));
		props.setLook(wBirthDateFieldName);
		wBirthDateFieldName.addModifyListener(lsMod);
		fdBirthDateFieldName = new FormData();
		fdBirthDateFieldName.left = new FormAttachment(middle, -margin);
		fdBirthDateFieldName.top = new FormAttachment(wLogicalFieldName, margin);
		fdBirthDateFieldName.right = new FormAttachment(100, 0);
		wBirthDateFieldName.setLayoutData(fdBirthDateFieldName);

		// sexField fieldname ...
		wlSexFieldName = new Label(wOutputFields, SWT.RIGHT);
		wlSexFieldName.setText(BaseMessages.getString(PKG,
				"PeselValidatorStepDialog.SexField.Label")); //$NON-NLS-1$
		props.setLook(wlSexFieldName);
		fdlSexFieldName = new FormData();
		fdlSexFieldName.left = new FormAttachment(0, -margin);
		fdlSexFieldName.right = new FormAttachment(middle, -2 * margin);
		fdlSexFieldName.top = new FormAttachment(wBirthDateFieldName, margin);
		wlSexFieldName.setLayoutData(fdlSexFieldName);

		wSexFieldName = new TextVar(transMeta, wOutputFields, SWT.SINGLE
				| SWT.LEFT | SWT.BORDER);
		wSexFieldName.setToolTipText(BaseMessages.getString(PKG,
				"PeselValidatorStepDialog.SexField.Tooltip"));
		props.setLook(wSexFieldName);
		wSexFieldName.addModifyListener(lsMod);
		fdSexFieldName = new FormData();
		fdSexFieldName.left = new FormAttachment(middle, -margin);
		fdSexFieldName.top = new FormAttachment(wBirthDateFieldName, margin);
		fdSexFieldName.right = new FormAttachment(100, 0);
		wSexFieldName.setLayoutData(fdSexFieldName);

		fdAdditionalFields = new FormData();
		fdAdditionalFields.left = new FormAttachment(0, margin);
		fdAdditionalFields.top = new FormAttachment(wFieldToValidateName, 2 * margin);
		fdAdditionalFields.right = new FormAttachment(100, -margin);
		wOutputFields.setLayoutData(fdAdditionalFields);

		//////////////////////////////////
		// END OF Additional Fields GROUP //
		//////////////////////////////////

		// THE BUTTONS
		wOK = new Button(shell, SWT.PUSH);
		wOK.setText(BaseMessages.getString(PKG, "System.Button.OK")); //$NON-NLS-1$
		wCancel = new Button(shell, SWT.PUSH);
		wCancel.setText(BaseMessages.getString(PKG, "System.Button.Cancel")); //$NON-NLS-1$

		setButtonPositions(new Button[] { wOK, wCancel }, margin, wOutputFields);

		// Add listeners
		lsOK = new Listener() {
			public void handleEvent(Event e) {
				ok();
			}
		};

		lsCancel = new Listener() {
			public void handleEvent(Event e) {
				cancel();
			}
		};

		wOK.addListener(SWT.Selection, lsOK);
		wCancel.addListener(SWT.Selection, lsCancel);

		lsDef = new SelectionAdapter() {
			public void widgetDefaultSelected(SelectionEvent e) {
				ok();
			}
		};

		wStepname.addSelectionListener(lsDef);

		// Detect X or ALT-F4 or something that kills this window...
		shell.addShellListener(new ShellAdapter() {
			public void shellClosed(ShellEvent e) {
				cancel();
			}
		});

		// Set the shell size, based upon previous time...
		setSize();

		getData();

		input.setChanged(changed);

		shell.open();
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch())
				display.sleep();
		}
		return stepname;
	}

	/**
	 * Copy information from the meta-data input to the dialog fields.
	 */
	public void getData() {
		if (input.getProcessedFieldName() != null)
			wFieldToValidateName.setText(input.getProcessedFieldName());
		if (input.getLogicalFieldName() != null)
			wLogicalFieldName.setText(input.getLogicalFieldName());
		if (input.getBirthDateFieldName() != null)
			wBirthDateFieldName.setText(input.getBirthDateFieldName());
		if (input.getSexFieldName() != null)
			wSexFieldName.setText(input.getSexFieldName());
	}

	private void cancel() {
		stepname = null;
		input.setChanged(changed);
		dispose();
	}

	private void ok() {
		if (Const.isEmpty(wStepname.getText()))
			return;
		input.setProcessedFieldName(wFieldToValidateName.getText());
		input.setLogicalFieldName(wLogicalFieldName.getText());
		input.setBirthDateFieldName(wBirthDateFieldName.getText());
		input.setSexFieldName(wSexFieldName.getText());
		stepname =  wStepname.getText();
		dispose();
	}

	private void get() {
		if (!gotPreviousFields) {
			try {
				String columnName = wFieldToValidateName.getText();
				wFieldToValidateName.removeAll();
				RowMetaInterface r = transMeta.getPrevStepFields(stepname);
				if (r != null) {
					r.getFieldNames();

					for (int i = 0; i < r.getFieldNames().length; i++) {
						wFieldToValidateName.add(r.getFieldNames()[i]);
					}
				}
				wFieldToValidateName.setText(columnName);
				gotPreviousFields = true;
			} catch (KettleException ke) {
				new ErrorDialog(
						shell,
						BaseMessages
								.getString(PKG,
										"PeselValidatorStepDialog.FailedToGetFields.DialogTitle"), BaseMessages.getString(PKG, "PeselValidatorStepDialog.FailedToGetFields.DialogMessage"), ke); //$NON-NLS-1$ //$NON-NLS-2$
			}
		}
	}

	public String toString() {
		return this.getClass().getName();
	}
}